package com.test.xshang.pattern.proxy;

import com.test.xshang.pattern.proxy.cglib.AlipayMethodInterceptor;
import com.test.xshang.pattern.proxy.cglib.CglibUtil;
import com.test.xshang.pattern.proxy.impl.CommonPayment;
import com.test.xshang.pattern.proxy.impl.ToCPaymentImpl;

/**
 * @BelongsProject: simpleframework
 * @BelongsPackage: com.test.xshang.pattern.proxy
 * @Author: xshang
 * @CreateTime: 2023-06-26  21:16
 * @Description: TODO
 * @Version: 1.0
 */
public class ProxyDemo {

    public static void main(String[] args) {
        // proxy 实现测试
        // 静态代理模式的实现
        // 代理对象需要在编译的时候就实现了  需要用户硬编码
        // 针对不同的目标对象类型 都需要单独实现代理对象(横切逻辑相同)
//        AlipayToC alipayToC = new AlipayToC(new ToCPaymentImpl());
//        alipayToC.pay();
//        AlipayToB alipayToB = new AlipayToB(new ToBPaymentImpl());
//       alipayToB.pay();
//        System.out.println("=============================================================================");
        // JDK动态代理 (要求  被代理的类  必须实现接口)
        // 类是通过类加载器加载的  在加载阶段主要完成两件事情
        // 1.通过带有包名的类来获取对应的class文件的二进制字节流
        // 2.根据读取到的字节流,将代表的静态存储结构转化为运行时数据结构
                    // 根据一定规则去改动或者生成新的字节流,动态的将切面逻辑织入其中  这种机制就是动态代理机制
                    // 会根据接口或者目标类,计算出代理类的字节码并加载到JVM中
        // 3.生成一个代表该类的class对象, 作为方法区该类的数据访问入口
        // 代理逻辑可以复用
//        ToCPayment toCPayment = new ToCPaymentImpl();
//        ToBPayment toBPayment = new ToBPaymentImpl();
//
//        InvocationHandler invocationHandler = new AlipayInvocationHandler(toBPayment);
//        ToBPayment toc = JdkDynamicProxyUtil.newProxyInstance(toBPayment, invocationHandler);
//        toc.pay();
        System.out.println("=============================================================================");
        // CGLIB动态代理
        /**
         * 代码生成库: code Generation Library
         *  不要求被代理类实现接口
         *  内部主要封装了ASM java字节码操控框架
         *  动态生成子类以覆盖非final的方法,绑定钩子回调自定义拦截器
         */
        System.out.println("==========================不实现接口====================================");
        CommonPayment commonPayment = new CommonPayment();
        AlipayMethodInterceptor interceptor = new AlipayMethodInterceptor();
        CommonPayment payment = CglibUtil.creatProxy(commonPayment, interceptor);
        payment.pay();
        System.out.println("==========================实现接口====================================");
        ToCPayment toCPayment = new ToCPaymentImpl();
        ToCPayment cPayment = CglibUtil.creatProxy(toCPayment, interceptor);
        cPayment.pay();

        /*
        结论  cglib更牛逼

            JDK动态代理: 基于反射机制实现,要求业务类必须实现接口    JDK原生,在JVM里运行较为可靠  平滑支持JDK版本升级
            CGLIB: 基于ASM机制实现,生成业务类的子类作为代理类  被代理对象无需实现接口,能实现代理类的无侵入编码
                两者执行效率: jdk经过多轮优化,现性能不相上下

        Spring AOP底层机制
        CGLIB 和 JDK动态代理 共存
        默认策略: Bean实现了接口则用JDK,否则使用CGLIB


        jdk兼容性更好, 无需额外依赖
         */


    }
}
